#include <stack>
#include <string>

class Calculator
{
private:
    std::stack<double> *operNumber; //操作数
    std::stack<char> *operSign;  //操作符
    bool sign;
    char pre;
    std::string s;

public:
    Calculator();
    ~Calculator();

    double Calcualte(const std::string &s);  //计算
    bool Make_Str();    //合法性判断
    bool isNumber(const char &ch);    //数字检测
    bool isLegalSign(const char &ch);   //操作符检测
    char Procede(const char &oper);    //优先级调整
    double Compute(const double &a, const double &b, const char &oper); //计算
};

using namespace std;

/**
 * @brief Construct a new Calculator:: Calculator object
 * 
 */
Calculator::Calculator()
{
    this->operNumber = new stack<double>();
    this->operSign = new stack<char>();
    this->sign = true;
    this->pre = '#';
    operSign->push('#');
}

/**
 * @brief 计算表达式的值
 * 
 * @param s 表达式字符串
 * @return double 结果
 */
double Calculator::Calcualte(const string &s)
{
    this->s = s + "#";
    if (this->Make_Str())
    {
        double ans = operNumber->top();
        operNumber->pop();
        return ans;
    }
    else
    {
        cout << "ERROR" << endl;
        return 0;
    }
}

/**
 * @brief 合法性检查
 * 
 * @return true 合法
 * @return false 不合法
 */
bool Calculator::Make_Str()
{
    for (string::iterator it = this->s.begin(); it != this->s.end();)
    {
        if (this->isNumber(*it))
        {
            double temp = 0.0;
            do
            {
                temp *= 10;
                temp += (*it - '0');
                pre = *it;
                it++;
            } while (this->isNumber(*it));

            if (*it == '.')
            {
                it++;
                double lesser = 0.1;
                while (this->isNumber(*it))
                {
                    temp += (*it - '0') * lesser;
                    lesser *= 0.1;
                    pre = *it;
                    it++;
                }
            }

            if (!sign)
            {
                temp = -temp;
                sign = true;
            }
            this->operNumber->push(temp);
        }
        else if (*it == '-' && (pre == '#' || pre == '('))
        {
            sign = false;
            it++;
        }
        else
        {
            if (!this->isLegalSign(*it))
            {
                cout << "ERROR INPUT STRING" << endl;
                return false;
            }
        }

        switch (this->Procede(*it))
        {
        case '<':
        {
            operSign->push(*it);
            pre = *it;
            it++;
            break;
        }
        case '=':
        {
            operSign->pop();
            pre = *it;
            it++;
            break;
        }
        case '>':
        {
            char oper = operSign->top();
            operSign->pop();
            double a = operNumber->top();
            operNumber->pop();
            double b = operNumber->top();
            operNumber->pop();

            operNumber->push(this->Compute(a, b, oper));

            break;
        }

        case 0:
        {
            cout << "ERROR ()" << endl;
            return false;
        }
        }
    }
    return true;
}

/**
 * @brief 数值合法性检查
 * 
 * @param ch 输入字符
 * @return true 合法
 * @return false 不合法
 */
bool Calculator::isNumber(const char &ch)
{
    if (ch >= '0' && ch <= '9')
    {
        return true;
    }
    return false;
}

/**
 * @brief 根据操作数与操作符计算结果
 * 
 * @param a 操作数1
 * @param b 操作数2
 * @param oper 操作符
 * @return double 计算值
 */
double Calculator::Compute(const double &a, const double &b, const char &oper)
{
    if (oper == '+')
    {
        return a + b;
    }
    if (oper == '-')
    {
        return a - b;
    }
    if (oper == '*')
    {
        return a * b;
    }
    if (oper == '/')
    {
        return a / b;
    }
}

/**
 * @brief 优先级比较
 * 
 * @param oper 操作符
 * @return char 优先级
 */
char Calculator::Procede(const char &oper)
{
    char top = this->operSign->top();
    if (top == '+' || top == '-')
    {
        if (oper == '*' || oper == '/' || oper == '(')
        {
            return '<';
        }
        return '>';
    }
    if (top == '*' || top == '/')
    {
        if (oper == '(')
        {
            return '<';
        }
        return '>';
    }
    if (top == '(')
    {
        if (oper == ')')
        {
            return '=';
        }
        else if (oper != '#')
        {
            return '<';
        }
    }
    if (top == ')' && oper != '(')
    {
        return '>';
    }
    if (top == '#')
    {
        if (oper == '#')
        {
            return '=';
        }
        else if (oper != ')')
        {
            return '<';
        }
    }
    return 0;
}

/**
 * @brief 操作符合法性判断
 * 
 * @param ch 操作符
 * @return true 合法
 * @return false 不合法
 */
bool Calculator::isLegalSign(const char &ch)
{
    if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')' || ch == '#')
    {
        return true;
    }
    return false;
}

/**
 * @brief Destroy the Calculator:: Calculator object
 * 
 */
Calculator::~Calculator()
{
}